using NBehave.Narrator.Framework;
using NBehave.Spec.MbUnit;
using Pentago.Core;

namespace Pentago.Specifications
{
    [Theme("Play game")] // these should really be written at the GameMaster level
    public class PlayGameSpecifications
    {
        [Story]
        public void Should_play_turn()
        {
            IGameBoard board = null;
            IGameBlock gameBlock1 = null;
            IGameBlock gameBlock2 = null;

            var story = new Story("Play turn");
            story.AsA("a player")
                .IWant("to place a marble on a game block and twist a game block a notch")
                .SoThat("i can WIN... or at least advance my position");

            story.WithScenario("Place first marble and twist neutral game block")
                .Given("an empty board", () =>
                                             {
                                                 gameBlock1 = new GameBlock(1);
                                                 gameBlock2 = new GameBlock(2);
                                                 board = new GameBoard(gameBlock1, gameBlock2, null, null);
                                             })
                .When("i place the first marble", 1, 1, Marble.Black, board.PlaceMarble)
                .And("twist a neutral block", 2, Direction.Clockwise, board.TwistBlock)
                .Then("the game board is updated", () =>
                                             {
                                                 new GameBlockSetup().AddBlackMarblesToLocations(1).ShouldContainTheSameMarblesAs(gameBlock1);
                                                 new GameBlockSetup().ShouldContainTheSameMarblesAs(gameBlock2);
                                              });

            story.WithScenario("Place first marble and twist non-neutral game block")
                .Given("an empty board", () =>
                                             {
                                                 gameBlock1 = new GameBlock(1);
                                                 board = new GameBoard(gameBlock1, null, null, null);
                                             })
                .When("i place the first marble", 1, 1, Marble.Black, board.PlaceMarble)
                .And("twist a non-neutral block", 1, Direction.Clockwise, board.TwistBlock)
                .Then("the game board is updated", () =>
                                                 new GameBlockSetup().AddBlackMarblesToLocations(3).ShouldContainTheSameMarblesAs(gameBlock1));

            story.WithScenario("Try to place subsequent marble and error")
                .Given("an board with 1 marble", () =>
                                             {
                                                 gameBlock1 = new GameBlock(1);
                                                 board = new GameBoard(gameBlock1, null, null, null);

                                                 board.PlaceMarble(1, 1, Marble.Black);
                                             })
                .When("i place a second marble in an already occupied location", () => { })
                .Then("i get told this is not a valid action", () => 
                                                 (typeof (PositionOccupiedException)).ShouldBeThrownBy(() => board.PlaceMarble(1, 1, Marble.White)));
        }
    }
}